package model

import (
	"encoding/base64"
	"fmt"
	"ginblog/utils/errmsg"
	"golang.org/x/crypto/bcrypt"
	"golang.org/x/crypto/scrypt"
	"gorm.io/gorm"
	"log"
)

type User struct {
	gorm.Model
	Username string `gorm:"type:varchar(20);not null " json:"username" validate:"required,min=4,max=12" label:"用户名" form:"username"`
	Password string `gorm:"type:varchar(500);not null" json:"password" validate:"required,min=6,max=120" label:"密码" form:"password"`
	Role     int    `gorm:"type:int;DEFAULT:2" json:"role" validate:"required,gte=2" label:"角色码" form:"role"`
}

// 查询用户是否存在
func CheckUser(username string) int {
	var user User
	// 查询这个用户名的id，存放在user对象中
	db.Debug().Select("id").Where("username = ?", username).First(&user)
	// 判断如果用的id存在，大于0，则用户存在，返回
	if user.ID > 0 {
		return errmsg.ERROR_USERNAME_USED // 用户存在的状态吗
	}

	//err := db.Debug().Table("user").Where("username = ?", username).First(&user).Error
	//if err != nil {
	//	return errmsg.ERROR_USERNAME_USED
	//}
	return errmsg.SUCCESS
}

// 添加用户的方法，结构体方法
func CreateUser(data *User) int {
	// data.Password = ScryptPw(data.Password)
	data.BeforeSave() //钩子函数调用，名字不一样需要调用
	err := db.Debug().Create(&data).Error
	if err != nil {
		fmt.Println(err)
		return errmsg.ERROR // 500的错误状态码
	}

	return errmsg.SUCCESS
}

// 查询用户列表
func GetUserList(pageSize int, pageNum int) ([]User, int64) {
	var userList []User
	var total int64
	//  分页  一页多少条数据，  偏移量
	// 存放在切片中
	err := db.Debug().Select("id,username,role,created_at").Limit(pageSize).Offset((pageNum - 1) * pageSize).Find(&userList)

	//err := db.Debug().Select("*").Limit(pageSize).Offset((pageNum - 1) * pageSize).Find(&userList) // err := db.Select("id,username,role,created_at").Limit(pageSize).Offset((pageNum - 1) * pageSize).Find(&users)
	err = db.Debug().Model(&userList).Count(&total)
	if err.Error != nil {
		fmt.Println("查询异常了！！")
		fmt.Println(err.Error)
		return nil, 0
	}
	return userList, total

}

// 编辑用户
func EditUser(id int, data *User) (*User, int) {
	var user User
	var maps = make(map[string]interface{})
	maps["username"] = data.Username
	maps["role"] = data.Role

	err := db.Debug().Model(&user).Where("id = ? ", id).Updates(maps).Error
	if err != nil {
		return nil, errmsg.ERROR
	}
	return &user, errmsg.SUCCESS
}

// 钩子函数密码加密
func (u *User) BeforeSave() {
	u.Password = ScryptPw(u.Password)
}

// 密码加盐
func ScryptPw(password string) string {
	const keyLen = 10
	salt := make([]byte, 8)
	salt = []byte{12, 32, 4, 6, 66, 22, 222, 11}
	//密码加盐加密
	HashPw, err := scrypt.Key([]byte(password), salt, 16384, 8, 1, keyLen)
	if err != nil {
		log.Fatal(err)
	}
	// base64编码成字符串
	fpw := base64.StdEncoding.EncodeToString(HashPw)
	return fpw

}

// 删除用户
func DeleteUser(id int) int {
	var user User
	err := db.Debug().Where("id = ? ", id).Delete(&user).Error
	if err != nil {
		return errmsg.ERROR
	}
	return errmsg.SUCCESS
}

// 查询单个用户
func GetUser(id int) (User, int) {
	var user User
	err := db.Limit(1).Where("ID = ?", id).Find(&user).Error
	if err != nil {
		return user, errmsg.ERROR
	}
	return user, errmsg.SUCCESS
}

// 前台登录 CheckLoginFront

func CheckLoginFront(username string, password string) (User, int) {
	var user User
	var passwordErr error
	db.Debug().Where("username = ?", username).First(&user)
	passwordErr = bcrypt.CompareHashAndPassword([]byte(password), []byte(password))
	if user.ID == 0 {
		return user, errmsg.ERROR_USER_NOT_EXIST
	}
	if passwordErr != nil {
		return user, errmsg.ERROR_PASSWORD_WRONG
	}
	return user, errmsg.SUCCESS
}

// 登录验证，后台登录
func CheckLogin(username, password string) (User, int) {
	var user User
	db.Debug().Where("username = ?", username).First(&user)
	if user.ID == 0 {
		return user, errmsg.ERROR_USER_NOT_EXIST
	}
	if ScryptPw(password) != user.Password {
		fmt.Println(ScryptPw(password))
		return user, errmsg.ERROR_PASSWORD_WRONG
	}
	if user.Role != 1 {
		return user, errmsg.ERROR_USER_NO_RIGHT
	}
	return user, errmsg.SUCCESS

}
